use serde::Deserialize;
use sqlx::{MySqlPool, FromRow, mysql::MySqlRow};

use crate::utils::result::{List};

// 分页 结构体
#[derive(Deserialize)]
pub struct PageParams {
    page_current: Option<i16>,
    page_size: Option<i16>
}

pub struct Page<'a> {
    pub db_conn: &'a MySqlPool,
    pub table_name: String,
    pub page_current: i16,
    pub page_size: i16,
}
impl Page<'_> {
    pub fn new(db_conn: &MySqlPool, table_name: String) -> Page {
        Page { db_conn, table_name, page_size: 10, page_current: 1 }
    }

    pub async fn list<T>(self, page_where: Option<String>, page_params: PageParams) -> List<T> 
    where
        T: for<'r> FromRow<'r, MySqlRow> + std::marker::Send + Unpin
    {
        let page_current = page_params.page_current.unwrap_or_else(|| self.page_current);
        let page_size = page_params.page_size.unwrap_or_else(|| self.page_size);
        let page_where = page_where.unwrap_or_else(|| "1".to_string());

        let data_sql = format!("SELECT * from {} where {} limit {},{}", self.table_name, page_where, (page_current - 1) * page_size, page_size);
        let total_sql = format!("SELECT count(*) from {} where {}", self.table_name, page_where);
        
        let total = sqlx::query_scalar(&total_sql).fetch_one(self.db_conn).await.unwrap();
        let data = sqlx::query_as::<_, T>(&data_sql).fetch_all(self.db_conn).await.unwrap();
        List { data, total }
    } 
}